import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConjecturaCollatzParalelo extends Thread {

	private static ConcurrentHashMap<Integer, String> seq = new ConcurrentHashMap<Integer, String>();
	private List<Integer> input;

	public ConjecturaCollatzParalelo(List<Integer> input) {
		this.input = input;
	}

	public void conjectura() {
		for (int i = 0; i < this.input.size(); i++) {
			Long atual = (long) this.input.get(i);
			while (atual != 1) {
				if (isEven(atual)) {
					atual = atual / 2;
				} else {
					atual = (3 * atual) + 1;
				}
			}
			seq.put(this.input.get(i), "Pertence a Conjectura");
		}
	}

	private boolean isEven(long number) {
		return number % 2 == 0;
	}

	public void run() {
		conjectura();
	}

	public List<Integer> getInput() {
		return input;
	}

	public void setInput(List<Integer> input) {
		this.input = input;
	}

	public Map<Integer, String> getSeq() {
		return seq;
	}

	public void setSeq(ConcurrentHashMap<Integer, String> seq) {
		ConjecturaCollatzParalelo.seq = seq;
	}

	public static void main(String[] args) {
		int n = Integer.parseInt(args[0]);
		List<Integer> numeros = NumberGenerator.generateNumber(n);

		// Sequencial
		ConjecturaCollatz conjectura = new ConjecturaCollatz(numeros);

		Long inicio = new GregorianCalendar().getTimeInMillis();
		Map<Integer, String> result2 = conjectura.conjectura();

		Long fim = new GregorianCalendar().getTimeInMillis();
		System.out.println("1 " + numeros.size() + " " + (fim - inicio));

		// Duas Threads
		ConjecturaCollatzParalelo conjecturaThread1 = new ConjecturaCollatzParalelo(
				numeros.subList(0, numeros.size() / 2));
		ConjecturaCollatzParalelo conjecturaThread2 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() / 2, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		ConcurrentHashMap<Integer, String> result = ConjecturaCollatzParalelo.seq;

		System.out.println("2 " + numeros.size() + " " + (fim - inicio));
		
		// Tres Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 3));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 3, numeros.size() * 2 / 3));
		ConjecturaCollatzParalelo conjecturaThread3 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 2 / 3, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("3 " + numeros.size() + " " + (fim - inicio));
		
		// Quatro Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 84));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 4, numeros.size() * 2 / 4));
		conjecturaThread3 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 2 / 4, numeros.size() * 3 / 4));
		ConjecturaCollatzParalelo conjecturaThread4 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 3 / 4, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();
		conjecturaThread4.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
			conjecturaThread4.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("4 " + numeros.size() + " " + (fim - inicio));
		
		// Cinco Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 5));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 5, numeros.size() * 2 / 5));
		conjecturaThread3 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 2 / 5, numeros.size() * 3 / 5));
		conjecturaThread4 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 3 / 5, numeros.size() * 4 / 5));
		ConjecturaCollatzParalelo conjecturaThread5 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 4 / 5, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();
		conjecturaThread4.start();
		conjecturaThread5.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
			conjecturaThread4.join();
			conjecturaThread5.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("5 " + numeros.size() + " " + (fim - inicio));
		// Seis Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 6));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 6, numeros.size() * 2 / 6));
		conjecturaThread3 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 2 / 6, numeros.size() * 3 / 6));
		conjecturaThread4 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 3 / 6, numeros.size() * 4 / 6));
		conjecturaThread5 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 4 / 6, numeros.size() * 5 / 6));
		ConjecturaCollatzParalelo conjecturaThread6 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 5 / 6, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();
		conjecturaThread4.start();
		conjecturaThread5.start();
		conjecturaThread6.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
			conjecturaThread4.join();
			conjecturaThread5.join();
			conjecturaThread6.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("6 " + numeros.size() + " " + (fim - inicio));
		// Sete Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 7));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 7, numeros.size() * 2 / 7));
		conjecturaThread3 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 2 / 7, numeros.size() * 3 / 7));
		conjecturaThread4 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 3 / 7, numeros.size() * 4 / 7));
		conjecturaThread5 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 4 / 7, numeros.size() * 5 / 7));
		conjecturaThread6 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 5 / 7, numeros.size() * 6 / 7));
		ConjecturaCollatzParalelo conjecturaThread7 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 6 / 7, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();
		conjecturaThread4.start();
		conjecturaThread5.start();
		conjecturaThread6.start();
		conjecturaThread7.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
			conjecturaThread4.join();
			conjecturaThread5.join();
			conjecturaThread6.join();
			conjecturaThread7.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("7 " + numeros.size() + " " + (fim - inicio));
		// Oito Threads
		conjecturaThread1 = new ConjecturaCollatzParalelo(numeros.subList(0,
				numeros.size() / 8));
		conjecturaThread2 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() / 8, numeros.size() * 2 / 8));
		conjecturaThread3 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 2 / 8, numeros.size() * 3 / 8));
		conjecturaThread4 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 3 / 8, numeros.size() * 4 / 8));
		conjecturaThread5 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 4 / 8, numeros.size() * 5 / 8));
		conjecturaThread6 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 5 / 8, numeros.size() * 6 / 8));
		conjecturaThread7 = new ConjecturaCollatzParalelo(numeros.subList(
				numeros.size() * 6 / 8, numeros.size() * 7 / 8));
		ConjecturaCollatzParalelo conjecturaThread8 = new ConjecturaCollatzParalelo(
				numeros.subList(numeros.size() * 7 / 8, numeros.size()));

		inicio = new GregorianCalendar().getTimeInMillis();
		conjecturaThread1.start();
		conjecturaThread2.start();
		conjecturaThread3.start();
		conjecturaThread4.start();
		conjecturaThread5.start();
		conjecturaThread6.start();
		conjecturaThread7.start();
		conjecturaThread8.start();

		try {
			conjecturaThread1.join();
			conjecturaThread2.join();
			conjecturaThread3.join();
			conjecturaThread4.join();
			conjecturaThread5.join();
			conjecturaThread6.join();
			conjecturaThread7.join();
			conjecturaThread8.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		fim = new GregorianCalendar().getTimeInMillis();
		result = ConjecturaCollatzParalelo.seq;

		System.out.println("8 " + numeros.size() + " " + (fim - inicio));
	}

}
